from random import randrange
#from SimDisMeasurments import *
import random
import numpy
from ReadWrite import *
from SimDisMeasurment import *
import sys
# k - number of clusters

# We should define number of songs somehow
number_of_songs = 386214

def cluster(medoiddata, data):
    
    cluster_list = [[] for k in range(0,len(medoiddata))]
    cluster_SSE = [0 for k in range(0,len(medoiddata))]
    medoidMagnitudes = []
    
    for medoid in medoiddata:
        medoidMagnitude = math.sqrt(dot(medoid,medoid))
        medoidMagnitudes.append(medoidMagnitude)
    
    for user in xrange(len(data)):
        usersongs = data[user]
        uservector = [k[1] for k in usersongs]
        userMagnitude = math.sqrt(dot(uservector,uservector))
        
        #mediandistance = []
        mostsimilar = 0
        bestdistance = sys.maxint
        for medoid in xrange(len(medoiddata)):   
            medoidsongs = medoiddata[medoid]
            #distance = cosineSimilaritylist(usersongs, medoidsongs, medoidMagnitudes[medoid], userMagnitude)
            distance = Euclidean(usersongs, medoidsongs)
            
            if distance < bestdistance:
                bestdistance = distance
                mostsimilar = medoid
            #mediandistance.append((medoid, distance))
        #m = max(mediandistance, key = lambda a:a[1])
        #cluster_list[m[0]].append(user)        
        cluster_list[mostsimilar].append(user)
        cluster_SSE[mostsimilar] += (bestdistance)*(bestdistance)
        #print('user ' + str(user) + ' is done')
    
    lenlist = [len(element) for element in cluster_list]
    
    for sse in xrange(len(cluster_SSE)):
        cluster_SSE[sse] /= lenlist[sse]
    
    print "sse for each cluster", cluster_SSE
    
    print 'sum of sum of squared error is: ' + str(sum(cluster_SSE))
    return cluster_list, sum(cluster_SSE) #, cluster_SSE    


def medoidsInitialization(k):
    medoids = list()
    for i in xrange(k):
        medoid = list()
        for j in xrange(number_of_songs):
            medoid.append(random.random())
        medoids.append(medoid)
    return medoids


#medoids = medoidsInitialization(4);
#print medoids

def terminate(median, median_old, threshold):

        difference = float(0)   
        for i in range(len(median)):
            for j in range(len(median[0])):
                difference += (median[i][j] - median_old[i][j])**2
                
        print difference
        '''
        if (difference<threshold):
            return True
        else:
            return False
        '''
        return False
        
    

    
terminate([[1, 3, 5],[3, 6, 7]], [[1, 3, 4],[5, 5, 8]], 1)


### Not tested, no idea if it works!
def calcMedoids(cluster_list, user_to_songs, num_songs):
    #
    num_cluster = len(cluster_list)
    newMedoid = numpy.zeros([num_cluster, num_songs])
    howmanyuserslistenedtosong = numpy.zeros([num_cluster, num_songs])
    howmanyuserslistenedtosong += 0.00001
    cluster_index = 0
    for cluster in cluster_list:
        if len(cluster)==0:
            print "a cluster got empty, so we reset it"
            newMediod[cluster_index,:]=medoidsInitialization(1)[0]
            howmanyuserslistenedtosong[cluster_index,:]= numpy.ones([num_cluster, num_songs])
        else:
            u = cluster[0]
            #print 'first user in cluster ' + str(cluster_index) + ' is ' + str(u)
            for user in cluster:
                #before it was
                #for song_freq in user_to_songs[user-1]:
                
                
                for song_freq in user_to_songs[user]:
                    #before it was
                    #newMedoid[cluster_index,song_freq[0]-1] += song_freq[1]
                    newMedoid[cluster_index,song_freq[0]] += song_freq[1]
                    
                    
                    #before it was
                    #howmanyuserslistenedtosong[cluster_index,song_freq[0]-1] += 1
                    howmanyuserslistenedtosong[cluster_index,song_freq[0]] += 1
        cluster_index += 1
            
    newMedoid = newMedoid/howmanyuserslistenedtosong
        
    #print newMedoid       
    return newMedoid


'''
cluster_list = [[1, 3, 5],[2, 4, 6]]
user_to_songs = [[(1, 3), (2, 1)],[(1, 5), (3, 2)],[(4, 2), (2, 1)],[(1, 3)],[(3, 4), (1, 3)],[(2, 4), (1, 4)]]
num_songs = 4
calcMedoids(cluster_list, user_to_songs, num_songs)
'''



maxiterations = 1000    
k = 100
terminationthreshold = 1

if __name__ == '__main__':
    print("main")
    data = readallidforcluster('../data/kaggle_visible_evaluation_triplets.txt')
    print('read data')
    oldmeans = medoidsInitialization(k)
    oldsumSSE = 0
    print('initialized')
    for i in range(1,maxiterations):
        cluster_list, sumSSE = cluster(oldmeans, data)
        writeobject('../data/cluster'+str(i)+'.txt', cluster_list)
        #print cluster_list[0][0:10]
        
        
        newmeans = calcMedoids(cluster_list, data, number_of_songs)
        #if terminate(oldmeans, newmeans, terminationthreshold):
        #    break
        
        if abs(oldsumSSE - sumSSE) < terminationthreshold:
            break
        oldmeans = newmeans
        print('done with interation ' + str(i))
        
    writeobject('../data/cluster'+str(k)+'.txt', cluster_list)
    
    
    
        
    
    